#include "Calculator.h"

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>

#include "database/TrackBase.h"
#include "io/HMMBuilder.h"
#include "io/BaseSaver.h"
#include "common.h"


Calculator::Calculator(std::string baseDir) {
	// Build recognizer
	const std::string baseSuffix(".lrn");
	std::string fileName = baseDir;
	std::vector<std::string> files = vector<string>();
	getdir(baseDir, files);

	// number of states
	const unsigned n = 5;
	// size of alphabet
	const unsigned m = 8;
	// max number of training iterations
	const unsigned maxIter = 100;
	// training delta
	const double delta = 0.001;
	// number of models
	double eps = 1.0e-10;
	
	std::cout << "base directory: " << baseDir << "\n";
	
	for (unsigned int i = 0; i < files.size(); i++) {
		if (files[i].size() >= 5 && files[i].substr(files[i].size() - 3) == "lrn") {
		    	std::cout << "add " << files[i] << "\n";
		    	std::string symbol = files[i].substr(0, files[i].size() - 4);
		    	std::cout << "symbol = " << symbol << "\n";
		    	rec.addModel(symbol, HMM());
		    	rec[symbol].initLRB(n, m, 0.5);
		    	//rec[symbol].print();
		    	HMMBuilder::build((baseDir + files[i]).c_str(), rec[symbol]);
			//rec[symbol].print();
		}
	}
}

void Calculator::isInterval(const LaserEvent& e) {
	printf("Listener notified about interval of time: %d.\n", e.time);
}
	
void Calculator::isTrack(const LaserEvent& e) {
	Track track = e.track;
	
	// number of states
	//const unsigned n = 5;
	// size of alphabet
	const unsigned m = 8;
	// max number of training iterations
	//const unsigned maxIter = 100;
	// training delta
	//const double delta = 0.001;
	// number of models
	//double eps = 1.0e-10;
	
	if (rec.size() == 0) {
		printf("symbol base is empty!\n");
		return;
	}
	
	// Recognize
	if (track.size() >= 10) {
		printf("track accepted.\n");
		Observation obs;
		track.convert(obs, m);
		
		printf("observation: ");
		for (size_t i = 0; i < obs.size(); i++) {
			printf("%d ", obs[i]);
		}
		printf("\n");
		
		std::string symbol = rec.recognize(obs);
		std::cout << "input recognized as " << symbol << "\n\n";
		expr += symbol;
		std::cout << "expression: " << expr << "\n\n";
	} else {
		printf("track rejected\n");
	}
}

int Calculator::evaluate() const {
	return evaluate(expr);
}

int intValue(std::string s) {
	size_t i = 0;
	for (; i < s.length() && (s[i] < '0' || s[i] > '9'); i++);
	return atoi(s.substr(i).c_str());
}

int Calculator::evaluate(std::string expr) {
	unsigned pr = 1;
	size_t imin = 0;
	unsigned minpr = -1;
	bool hasOper = false;
	for (size_t i = 0; i < expr.length(); i++) {
		unsigned curpr = -1;
		if (expr[i] == '+' || expr[i] == '-') {
			curpr = pr + 0;
		} else if (expr[i] == '*' || expr[i] == '/') {
			curpr = pr + 1;
		} else if (expr[i] == '(') {
			pr++;
		} else if (expr[i] == ')') {
			pr--;
		}
		if (curpr < minpr) {
			minpr = curpr;
			imin = i;
			hasOper = true;
		}
	}
	/*
	if (pr != 1) {
		std::cerr << "wrong expression!" << std::endl;
		return -1;
	}
	*/
	if (hasOper) {
		std::string left = expr.substr(0, imin);
		std::string right = expr.substr(imin + 1);
		int lval = evaluate(left);
		int rval = evaluate(right);
		std::cout << lval << expr[imin] << rval << std::endl;
		if (expr[imin] == '+') {
			return lval + rval;
		} else if (expr[imin] == '-') {
			return lval - rval;
		} else if (expr[imin] == '*') {
			return lval * rval;
		} else if (expr[imin] == '/') {
			return lval / rval;
		} else {
			std::cerr << "unknown operator: " << expr[imin] << std::endl;
			return -1;
		}
	} else {
		printf("%d\n", intValue(expr));
		return intValue(expr);
	}
	
	return 0;
}

